package com.zhz.mall.common.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.lang.Nullable;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * NumberUtils
 *
 * @author zzhouhengzhe
 */
public abstract class NumberUtils extends NumberUtil {
    public static final BigDecimal ZERO = new BigDecimal("0.00");

    /**
     * 是否是正数
     */
    public static boolean isPositive(@Nullable BigDecimal value) {
        return Objects.nonNull(value) && value.signum() > 0;
    }

    /**
     * 是否是正数
     */
    public static boolean isPositive(@Nullable Integer value) {
        return Objects.nonNull(value) && value > 0;
    }


    /**
     * 是否是负数
     */
    public static boolean isNegative(@Nullable BigDecimal value) {
        return Objects.nonNull(value) && value.signum() < 0;
    }


    /**
     * 是否为0
     */
    public static boolean isZero(@Nullable BigDecimal value) {
        return Objects.nonNull(value) && value.signum() == 0;
    }


    /**
     * 是否为 0 或 null
     */
    public static boolean isZeroOrNull(@Nullable BigDecimal value) {
        return Objects.isNull(value) || isZero(value);
    }


    /**
     * 四舍五入（保留两位小数）
     *
     * @return 新值（如果 value 为空返回 BigDecimal.ZERO）
     */
    public static BigDecimal round2(@Nullable BigDecimal value) {
        return clearZero(round(value, 2));
    }


    /**
     * 四舍五入（保留两位小数）
     */
    public static String round2Str(@Nullable BigDecimal value) {
        return round2(value).toString();
    }


    /**
     * 绝对值（null 则返回 0）
     */
    public static BigDecimal abs(@Nullable BigDecimal value) {
        return isZeroOrNull(value) ? BigDecimal.ZERO : value.abs();
    }


    /**
     * 负绝对值（null 则返回 0）
     */
    public static BigDecimal negativeAbs(@Nullable BigDecimal value) {
        return isZeroOrNull(value) ? BigDecimal.ZERO : value.abs().negate();
    }


    /**
     * 加法
     */
    public static BigDecimal add(@Nullable BigDecimal value1, @Nullable BigDecimal value2) {
        value1 = ObjectUtil.defaultIfNull(value1, BigDecimal.ZERO);
        value2 = ObjectUtil.defaultIfNull(value2, BigDecimal.ZERO);
        return value1.add(value2);
    }


    /**
     * 减法
     */
    public static BigDecimal sub(@Nullable BigDecimal value1, @Nullable BigDecimal value2) {
        value1 = ObjectUtil.defaultIfNull(value1, BigDecimal.ZERO);
        value2 = ObjectUtil.defaultIfNull(value2, BigDecimal.ZERO);
        return value1.subtract(value2);
    }


    /**
     * 求和
     */
    public static BigDecimal add(Collection<String> values) {
        if (CollUtil.isEmpty(values)) {
            return BigDecimal.ZERO;
        }
        return add(values.toArray(new String[0]));
    }


    /**
     * 求和
     */
    public static BigDecimal sum(Collection<BigDecimal> values) {
        if (CollUtil.isEmpty(values)) {
            return BigDecimal.ZERO;
        }
        return add(values.toArray(new BigDecimal[0]));
    }


    /**
     * 求差
     */
    public static BigDecimal sub(Collection<String> values) {
        if (CollUtil.isEmpty(values)) {
            return BigDecimal.ZERO;
        }
        return sub(values.toArray(new String[0]));
    }


    /**
     * 清除末尾多余的0（如: 1.010 -> 1.01）
     *
     * @param value 数字
     * @return 当 value 为 null 时默认返回 0
     */
    public static BigDecimal clearZero(@Nullable BigDecimal value) {
        if (Objects.isNull(value)) {
            return BigDecimal.ZERO;
        }
        if (value.scale() == 0) {
            return value;
        }
        return new BigDecimal(value.stripTrailingZeros().toPlainString());
    }


    /**
     * 清除末尾多余的0
     */
    public static String clearZero(String value) {
        return new BigDecimal(value).stripTrailingZeros().toPlainString();
    }


    /**
     * 比较大小，值相等 返回true<br>
     * 此方法通过调用{@link BigDecimal#compareTo(BigDecimal)}方法来判断是否相等<br>
     * 此方法判断值相等时忽略精度的，即0.00 == 0
     *
     * @param bigNum1 数字1
     * @param bigNum2 数字2
     * @return 是否相等
     */
    public static boolean equals(BigDecimal bigNum1, String bigNum2) {
        return equals(bigNum1, new BigDecimal(bigNum2));
    }


    public static boolean notEquals(BigDecimal bigNum1, BigDecimal bigNum2) {
        return !equals(bigNum1, bigNum2);
    }


    /**
     * 是否相等（忽略符号位）
     */
    public static boolean equalsIgnoreSign(BigDecimal bigNum1, BigDecimal bigNum2) {
        return equals(bigNum1.abs(), bigNum2.abs());
    }


    /**
     * 加法（保留2位小数）
     */
    public static BigDecimal addRound2(@Nullable BigDecimal bigNum1, @Nullable BigDecimal bigNum2) {
        return round2(add(bigNum1, bigNum2));
    }

    /**
     * 减法（保留2位小数）
     */
    public static BigDecimal subRound2(@Nullable BigDecimal bigNum1, @Nullable BigDecimal bigNum2) {
        return round2(sub(bigNum1, bigNum2));
    }

    /**
     * 是否是数字
     */
    public static boolean isNumber(Object value) {
        if (Objects.isNull(value)) {
            return false;
        }

        List<Class> numberTypes = Arrays.asList(BigDecimal.class, Integer.class, Long.class,
                Byte.class, Short.class, Double.class, Float.class);
        return numberTypes.contains(value.getClass());
    }


}
